import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:workmate/provider/global.dart';
import 'package:workmate/provider/theme.dart';
import 'package:workmate/widget/ico.dart';

class WebViewPage extends StatefulWidget {
  final String url;
  const WebViewPage(this.url, {Key? key}) : super(key: key);
  @override
  State<WebViewPage> createState() => _WebViewPageState();
}

class _WebViewPageState extends State<WebViewPage> {
  late WebViewController controller;
  String title = '';
  bool isLoading = true;
  late ThemeProvider theme;
  bool canGoForward = false;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color.fromARGB(0, 73, 17, 17))
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) async {
            if (progress == 100) {
              canGoForward = await controller.canGoForward();
              debugPrint('------$progress==$canGoForward');
              setState(() {});
            }
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) async {
            title = (await controller.getTitle())!;
            debugPrint('--onPageFinished---$title-$url');
            setState(() {});
          },
          onWebResourceError: (WebResourceError error) {},
        ),
      )
      // 注册一个flutter与web间的通信桥梁
      ..addJavaScriptChannel('Toaster',
          onMessageReceived: (JavaScriptMessage message) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(message.message)),
        );
      })
      ..loadRequest(Uri.parse(widget.url));
  }

  @override
  Widget build(BuildContext context) {
    theme = Provider.of<ThemeProvider>(context);
    return Scaffold(
        appBar: AppBar(
          toolbarHeight: 44,
          title: Text(title),
          centerTitle: true,
          leadingWidth: 88,
          leading: NavigationControls(controller, canGoForward: canGoForward),
          backgroundColor: theme.primaryColor,
          actions: <Widget>[MenuList(controller)],
        ),
        body: Container(
          height: 300,
          color: Colors.black,
          child: WebViewWidget(controller: controller),
        ));
  }
}

class NavigationControls extends StatelessWidget {
  const NavigationControls(this.controller,
      {Key? key, this.canGoForward = false})
      : super(key: key);
  final bool canGoForward;
  final WebViewController controller;

  static Widget _setIcon(String name,
      {double size = 18,
      Color? color,
      double width = 40,
      EdgeInsets margin = const EdgeInsets.all(0)}) {
    return Container(
        width: width,
        margin: margin,
        child: ICO.svg(name, size: size, color: color));
  }

  @override
  Widget build(BuildContext context) {
    return Row(mainAxisAlignment: MainAxisAlignment.start, children: [
      GestureDetector(
        onTap: () {
          controller.canGoBack().then((canGoBack) {
            if (canGoBack) {
              controller.goBack();
            } else {
              Navigator.pop(context, true);
            }
          });
        },
        child: _setIcon('arrow_left', color: Colors.white),
      ),
      GestureDetector(
          onTap: () {
            if (canGoForward) {
              controller.goForward();
            } else {
              // APP.layer.message('不能向前了。');
            }
          },
          child: _setIcon('arrow_right',
              color: canGoForward ? Colors.white : Colors.white10))
    ]);
  }
}

enum MenuOptions {
  refresh,
  showUserAgent,
  listCookies,
  clearCookies,
  addToCache,
  listCache,
  clearCache,
  navigationDelegate,
  doPostRequest,
  loadLocalFile,
  loadFlutterAsset,
  loadHtmlString,
  transparentBackground,
  setCookie,
}

const String kNavigationExamplePage = '''
<!DOCTYPE html><html>
<head><title>Navigation Delegate Example</title></head>
<body>
<p>
The navigation delegate is set to block navigation to the youtube website.
</p>
<ul>
<ul><a href="https://www.youtube.com/">https://www.youtube.com/</a></ul>
<ul><a href="https://www.google.cn/">https://www.google.cn/</a></ul>
</ul>
</body>
</html>
''';

const String kLocalExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>

<h1>Local demo page</h1>
<p>
  This is an example page used to demonstrate how to load a local file or HTML
  string using the <a href="https://pub.flutter-io.cn/packages/webview_flutter">Flutter
  webview</a> plugin.
</p>

</body>
</html>
''';

const String kTransparentBackgroundPage = '''
  <!DOCTYPE html>
  <html>
  <head>
    <title>Transparent background test</title>
  </head>
  <style type="text/css">
    body { background: transparent; margin: 0; padding: 0; }
    #container { position: relative; margin: 0; padding: 0; width: 100vw; height: 100vh; }
    #shape { background: red; width: 200px; height: 200px; margin: 0; padding: 0; position: absolute; top: calc(50% - 100px); left: calc(50% - 100px); }
    p { text-align: center; }
  </style>
  <body>
    <div id="container">
      <p>Transparent background test</p>
      <div id="shape"></div>
    </div>
  </body>
  </html>
''';

class MenuList extends StatelessWidget {
  MenuList(this.controller, {Key? key}) : super(key: key);

  final WebViewController controller;
  final WebViewCookieManager cookieManager = WebViewCookieManager();

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<MenuOptions>(
      padding: const EdgeInsets.only(left: 8, right: 8),
      onSelected: (MenuOptions value) {
        switch (value) {
          case MenuOptions.showUserAgent:
            _onShowUserAgent(context);
            break;
          case MenuOptions.listCookies:
            _onListCookies(context);
            break;
          case MenuOptions.clearCookies:
            _onClearCookies(context);
            break;
          case MenuOptions.addToCache:
            _onAddToCache(context);
            break;
          case MenuOptions.listCache:
            _onListCache();
            break;
          case MenuOptions.clearCache:
            _onClearCache(context);
            break;
          case MenuOptions.navigationDelegate:
            _onNavigationDelegateExample();
            break;
          case MenuOptions.doPostRequest:
            _onDoPostRequest();
            break;
          case MenuOptions.loadLocalFile:
            _onLoadLocalFileExample();
            break;
          case MenuOptions.loadFlutterAsset:
            _onLoadFlutterAssetExample();
            break;
          case MenuOptions.loadHtmlString:
            _onLoadHtmlStringExample();
            break;
          case MenuOptions.transparentBackground:
            _onTransparentBackground();
            break;
          case MenuOptions.setCookie:
            _onSetCookie();
            break;
          case MenuOptions.refresh:
            _onReresh(context);
            break;
        }
      },
      itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[
        PopupMenuItem<MenuOptions>(
          value: MenuOptions.refresh,
          child: _txtStyle('刷新'),
        ),
        PopupMenuItem<MenuOptions>(
          value: MenuOptions.showUserAgent,
          child: _txtStyle('用户代理'),
        ),
        PopupMenuItem<MenuOptions>(
          value: MenuOptions.clearCookies,
          child: _txtStyle('清除cookie'),
        ),
        PopupMenuItem<MenuOptions>(
          value: MenuOptions.clearCache,
          child: _txtStyle('清除缓存'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.listCookies,
          child: Text('List cookies'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.addToCache,
          child: Text('Add to cache'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.listCache,
          child: Text('List cache'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.navigationDelegate,
          child: Text('Navigation Delegate example'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.doPostRequest,
          child: Text('Post Request'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.loadHtmlString,
          child: Text('Load HTML string'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.loadLocalFile,
          child: Text('Load local file'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.loadFlutterAsset,
          child: Text('Load Flutter Asset'),
        ),
        const PopupMenuItem<MenuOptions>(
          key: ValueKey<String>('ShowTransparentBackgroundExample'),
          value: MenuOptions.transparentBackground,
          child: Text('Transparent background example'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.setCookie,
          child: Text('Set cookie'),
        ),
      ],
    );
  }

  Widget _txtStyle(String name) {
    return Text(
      name,
      style: const TextStyle(
        fontSize: 14,
      ),
    );
  }

  void _onReresh(BuildContext context) {
    controller.reload();
  }

  void _onShowUserAgent(BuildContext context) {
    // 将用户代理字符串消息发送到我们注册的Toaster JavaScript使用webview通道
    // controller
    //     .runJavaScript('alert("User Agent: " + navigator.userAgent);');

    controller.runJavaScriptReturningResult(
        'Toaster.postMessage("User Agent: " + navigator.userAgent + localStorage.getItem("test_localStorage"));');
  }

  void _onClearCache(BuildContext context) {
    controller.clearCache().then((value) {
      APP.layer.message('清除缓存成功');
      controller.clearLocalStorage();
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('Cache cleared.'),
      ));
    });
  }

  void _onClearCookies(BuildContext context) {
    cookieManager.clearCookies().then((hadCookies) {
      String message = '清除cookies成功';
      if (!hadCookies) {
        message = '没有需要清除的cookies';
      }
      APP.layer.message(message);
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text(message),
      ));
    });
  }

  Future<void> _onListCookies(BuildContext context) async {
    final String cookies =
        controller.runJavaScriptReturningResult('document.cookie') as String;
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          const Text('Cookies:'),
          _getCookieList(cookies),
        ],
      ),
    ));
  }

  Future<void> _onAddToCache(BuildContext context) async {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
      content: Text('Added a test entry to cache.'),
    ));
    await controller.runJavaScript(
      'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";',
    );
  }

  Future<void> _onListCache() {
    return controller.runJavaScript('''
        Toaster.postMessage(JSON.stringify(window.test()));
        // caches.keys()
        // .then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))
        // .then((caches) => Toaster.postMessage(caches))
        ''');
  }

  Future<void> _onNavigationDelegateExample() {
    final String contentBase64 = base64Encode(
      const Utf8Encoder().convert(kNavigationExamplePage),
    );
    return controller.loadRequest(
      Uri.parse('data:text/html;base64,$contentBase64'),
    );
  }

  Future<void> _onSetCookie() async {
    await cookieManager.setCookie(
      const WebViewCookie(
        name: 'foo',
        value: 'bar',
        domain: 'httpbin.org',
        path: '/anything',
      ),
    );
    await controller.loadRequest(Uri.parse(
      'https://httpbin.org/anything',
    ));
  }

  Future<void> _onDoPostRequest() {
    return controller.loadRequest(
      Uri.parse('https://httpbin.org/post'),
      method: LoadRequestMethod.post,
      headers: <String, String>{'foo': 'bar', 'Content-Type': 'text/plain'},
      body: Uint8List.fromList('Test Body'.codeUnits),
    );
  }

  Future<void> _onLoadLocalFileExample() async {
    final String pathToIndex = await _prepareLocalFile();
    await controller.loadFile(pathToIndex);
  }

  Future<void> _onLoadFlutterAssetExample() {
    return controller.loadFlutterAsset('assets/www/index.html');
  }

  Future<void> _onLoadHtmlStringExample() {
    return controller.loadHtmlString(kLocalExamplePage);
  }

  Future<void> _onTransparentBackground() {
    return controller.loadHtmlString(kTransparentBackgroundPage);
  }

  Widget _getCookieList(String? cookies) {
    if (cookies == null || cookies == '""') {
      return Container();
    }
    final List<String> cookieList = cookies.split(';');
    final Iterable<Text> cookieWidgets =
        cookieList.map((String cookie) => Text(cookie));
    return Column(
      mainAxisAlignment: MainAxisAlignment.end,
      mainAxisSize: MainAxisSize.min,
      children: cookieWidgets.toList(),
    );
  }

  static Future<String> _prepareLocalFile() async {
    final String tmpDir = (await getTemporaryDirectory()).path;
    final File indexFile = File(
        <String>{tmpDir, 'www', 'index.html'}.join(Platform.pathSeparator));

    await indexFile.create(recursive: true);
    await indexFile.writeAsString(kLocalExamplePage);
    return indexFile.path;
  }
}
